package admin

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"suci-go-zero/common/token"
	"suci-go-zero/common/xerr"
	"suci-go-zero/internal/model"
	"suci-go-zero/internal/svc"
	"suci-go-zero/internal/types"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
	"golang.org/x/crypto/bcrypt"
)

type UserLoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserLoginLogic {
	return &UserLoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *UserLoginLogic) UserLogin(req *types.Login) (resp *types.LoginRsp, err error) {
	resp = &types.LoginRsp{}
	//查找用户
	rb := l.svcCtx.Models.User.RowBuilder().Where("name=?", req.Name)
	user, err := l.svcCtx.Models.User.FindOneByQuery(l.ctx, rb)
	if err != nil && err != model.ErrNotFound {
		return nil, errors.Wrap(xerr.NewErrCode(xerr.DB_ERROR), fmt.Sprintf("查找用户失败%v", err))
	}

	if user == nil {
		return nil, errors.Wrap(xerr.NewErrCode(xerr.USER_NOT_FOUND), fmt.Sprintf("用户不存在请注册"))
	}

	if bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.PassWord)) != nil {
		return nil, errors.Wrap(xerr.NewErrCode(xerr.PW_ERROR), fmt.Sprintf("密码错误"))
	}
	resp.UserInfo = types.AdminUser{
		Id:       user.Id,
		Nickname: user.Nickname,
		RealName: user.RealName,
		Email:    user.Email,
		Name:     user.Name,
		Avatar:   user.Avatar,
		Role:     []types.AdminRole{},
	}
	//查找角色
	roldIdsStr := "(" + user.Roles + ")"
	rb = l.svcCtx.Models.Role.RowBuilder().Where(fmt.Sprintf("id in %s", roldIdsStr))
	roles, err := l.svcCtx.Models.Role.FindAll(l.ctx, rb, "")
	if err != nil && err != model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "role 查找失败%v", err)
	}
	if err == model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "role 查找失败%v 空", err)
	}

	rolesString := make([]string, 0)
	menuIds := make([]string, 0)
	for _, role := range roles {
		resp.UserInfo.Role = append(resp.UserInfo.Role, types.AdminRole{
			Id:     role.Id,
			Alias:  role.Alias,
			Label:  role.Label,
			Remark: role.Remark,
		})
		rolesString = append(rolesString, role.Alias)
		menuIds = append(menuIds, role.Menus)
	}

	//查找菜单

	menuidstr := "(" + strings.Join(menuIds, ",") + ")"
	logx.Info(menuidstr)
	rb = l.svcCtx.Models.Menu.RowBuilder().Where(fmt.Sprintf("id in %s", menuidstr))
	menuList, err := l.svcCtx.Models.Menu.FindAll(l.ctx, rb, "sort desc")
	if err != nil && err != model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找校色 数据库错误%v", err)
	}

	if err == model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_NOT_FOUND_ERR), "角色列表为空%v", err)
	}
	apiListMap := make(map[string]string)
	rb = l.svcCtx.Models.MenuApi.RowBuilder().Where(fmt.Sprintf("menu_id in %s", menuidstr))
	apiLists, err := l.svcCtx.Models.MenuApi.FindAll(l.ctx, rb, "")
	if err != nil && err != model.ErrNotFound {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "api 数据库错误%v", err)
	}

	for _, apiList := range apiLists {
		apiListMap[apiList.Url] = apiList.Code
	}

	li := make([]*types.MenuItem, 0)
	for _, mi := range menuList {
		meta := &types.Meta{}
		err = json.Unmarshal([]byte(mi.Meta), meta)
		if err != nil {
			logx.Info(err)
		}
		mn := &types.MenuItem{
			Id:        mi.Id,
			Pid:       mi.ParentId,
			Name:      mi.Name,
			Path:      mi.Path,
			Meta:      *meta,
			Component: mi.Component,
		}
		li = append(li, mn)
		resp.Permissions = append(resp.Permissions, mi.Name)
	}

	resp.Menu = getTreeRecursive(li, 0)
	tk, err := token.GetUserTokenStr(l.svcCtx.Config.JwtAuth.AccessSecret, time.Now().Unix(), l.svcCtx.Config.JwtAuth.AccessExpire, map[string]interface{}{
		"id":         user.Id,
		"jwt_user":   user,
		"permission": resp.Permissions,
		"roles":      rolesString,
		"api_list":   apiListMap,
	})

	if err != nil {
		return nil, errors.Wrap(xerr.NewErrCode(xerr.TOKEN_GENERATE_ERROR), fmt.Sprintf("生产token失败"))
	}
	resp.Token = tk

	return resp, nil
}
